/*! \file calls.h
	\author HiddenSeeker

	Defines a calls and field accessing nodes
*/
#include "../abstractnode.h"
#include "list.h"
#include <string>
#include "../../semantics/parentdata.h"
#pragma once

class CallInformation;
class MethodSelectDelegate;


/*! Class, that describes used behaviour of method access
*/
class AttributeCommand
{
 public:
         virtual ~AttributeCommand();
		 /*! Transforms a code, if needed to
			\return true on success
		 */
		 virtual bool checkLogic(ParentData * data);
         virtual bool canBeTrasnformedFromAssignment(ParentData * parent, bool * ok);
		 virtual bool isLValue(ParentData * data)=0;
		 /*! Checks common errors
		 */
		 virtual void checkCommonErrors(ParentData * data)=0;
		 virtual std::string getType(ParentData * data)=0;
		 /*! Fills a constant table for method
		  */
		 virtual void fillConstant(ParentData * data)=0;
		 /*! Produces a code for method
		  */
		 virtual void produceCode(ParentData * data)=0;
};

class Field;
struct Method;

class FieldGet : public AttributeCommand
{
 private:
	      Field * m_field;
		  unsigned short m_ref;
 public:
		inline FieldGet(Field * field)
		{
			m_field=field;
		}

		inline Field * field() { return m_field; }
		bool canBeTrasnformedFromAssignment(ParentData * parent, bool * ok);		
		virtual bool isLValue(ParentData * data);
		/*! Checks common errors
		 */
		virtual void checkCommonErrors(ParentData * data);
		 /*! Fills a constant table for method
		  */
		 virtual void fillConstant(ParentData * data);
		 /*! Produces a code for method
		  */
		 virtual void produceCode(ParentData * data);
		std::string getType(ParentData * data);
};

class MethodCall : public AttributeCommand
{
 private:
	      Method * m_method;
		  bool     m_pop_result;
		  
		  CallInformation  * m_info;
 public:
	    /*! Transforms a code, if needed to
			\return true on success
		 */
		 virtual bool checkLogic(ParentData * data);
		inline MethodCall(Method * method)
		{
			m_method=method;
			m_pop_result=false;
			m_info=NULL;
		}
		virtual bool isLValue(ParentData * data);
		/*! Checks common errors
		 */
		virtual void checkCommonErrors(ParentData * data);
		std::string getType(ParentData * data);
		 /*! Fills a constant table for method
		  */
		 virtual void fillConstant(ParentData * data);
		/*! Produces a code for method
		 */
		 virtual void produceCode(ParentData * data);

		~MethodCall();
};

class FieldAccess : public AbstractNode
{
 private:
	     Field * m_field;
		 std::string m_classname;
		 std::string m_fieldname;
		 Compound * m_args;
		 ClassSemantic * m_semantic;
 public:
	 inline Field * field() {
		return m_field;
	 }
	 inline std::string & fieldName() {
		return m_fieldname;
	 }
	 FieldAccess(Field * field, 
				 ClassSemantic * semantic,
		         const std::string & className, 
				 const std::string & fieldName,
				 Compound * args);
	
	 void write(GraphStream * stream);
	~FieldAccess();
	/*! Checks common errors
	 */
	virtual void checkCommonErrors(ParentData * data);
	std::string getType(ParentData * data);
};


class AttributeAccess: public AbstractNode
{
 protected:
 		   AbstractNode * m_exp;
		   std::string *  m_field;
		   Compound * m_args;
		   AttributeCommand * m_behaviour;

		   bool m_visited;
		   /*! Selects a class name
		    */
		   ClassSemantic * m_class_data;
		   bool m_kill;
 public:

	 inline ClassSemantic * callClassData()
	 {
		 return m_class_data;
	 }
	 inline AbstractNode * expression()
	 {
		 return m_exp;
	 }
	 /*! Return arguments for attributes
	  */
	 inline Compound * args() 
	 {
		 return m_args;
	 }
	 FieldAccess * createFieldAccess();
	 inline AttributeAccess(const YYLTYPE & pos,
		                    AbstractNode * exp,
		                    std::string * m_str,
							Compound     * args) : AbstractNode(pos)
	 {
		 m_field=m_str;
		 m_exp=exp;
		 m_args=args;
		 m_behaviour=NULL;
		 m_visited=false;
		 m_kill=true;
	 }

	 /*! Selects, whether we are field or method
		 \param[in] data
		 \param[in] field what we should select
		 \return true on success
	  */
	 bool selectFieldOrMethod(ParentData * data, bool field=false);
	 /*! Checks common errors
	  */
	 virtual void checkCommonErrors(ParentData * data);
	 /*! Transforms a code, if needed to
			\return true on success
	  */
	 virtual bool checkLogic(ParentData * data);
	 virtual bool isLValue(ParentData * data);
	 /*! Returns type, returned by value
      */
	 virtual std::string getType(ParentData * data);
	 /*! Transforms from assignment
	  */
	 virtual bool canBeTransformedFromAssignment(ParentData * data, bool * error);
	 /*! Writes a node data to stream
	  */
	 virtual void write(GraphStream * s);
	 /*! Fills a constant table for method
	  */
	 virtual void fillConstant(ParentData * data);

	 /*! Produces a code for method
	  */
	 virtual void produceCode(ParentData * data);
	 /*! Destructor
 	  */
	 ~AttributeAccess();
};

/*! Node, which is used when user calls a constructor of object
    ![Type]!ID[.ID][(expr_list)]
*/
class CreationCall: public AbstractNode
{
  private:
	      AbstractNode * m_type;
		  std::string  * m_identifier;
		  std::string  * m_constructor_name;
		  Compound     * m_args;


		  unsigned char  m_local_arg_index;  //!< Used index
		  unsigned short m_constructor;      //!< Used constructor
		  unsigned short m_class;            //!< Used class for new

		  Method        * m_invoked_method;
		  ClassSemantic * m_class_data;
		  bool            m_pop_result;
		  CallInformation * m_info;
 public:
	 inline CreationCall(const YYLTYPE & pos,
		                 AbstractNode * type, 
						 std::string * idname,
						 std::string * consname,
						 Compound    * args): AbstractNode(pos)
	 {
		 m_type=type;
		 m_identifier=idname;
		 m_constructor_name=consname;
		 m_args=args;
		 m_info=NULL;
	 }
	 /*! Checks if returning result
	  */
	 virtual bool   isResultReturn();
	 /*! Checks, whether call is logic
	  */
	 bool checkLogic(ParentData * data);
	  /*! Checks common errors
	  */
	 virtual void checkCommonErrors(ParentData * data);
	 /*! Fills a constant table for method
	  */
	 virtual void fillConstant(ParentData * data);

	 /*! Produces a code for method
	  */
	 virtual void produceCode(ParentData * data);
	 /*! Writes a node data to stream
	  */
	 virtual void write(GraphStream * s);

	~CreationCall();
};

